Make gtk_tree_view_real_set_cursor() handle non-existing paths
authorKristian Rietveld <kris@gtk.org>
Fri, 28 Aug 2009 07:53:49 +0000 (09:53 +0200)
committerKristian Rietveld <kris@gtk.org>
Fri, 28 Aug 2009 09:04:54 +0000 (11:04 +0200)
Such paths (eg. a child node that is collapsed) should be ignored.  This
is fixed by checking the return value of _gtk_tree_view_find_node(),
which returns a partial return value (the parent node) when it returns
TRUE.  Also added a unit test.

gtk/gtktreeview.c
gtk/tests/treeview.c

index e3bee395bce36711d1b1b296949ff690d41f3c9d..9ef634fd0c553beb0226f8b99bf962082ca878b2 100644 (file)
@@ -12440,14 +12440,24 @@ gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
   gtk_tree_row_reference_free (tree_view->priv->cursor);
   tree_view->priv->cursor = NULL;
 
-  /* One cannot set the cursor on a separator. */
-  if (!row_is_separator (tree_view, NULL, path))
+  /* One cannot set the cursor on a separator.   Also, if
+   * _gtk_tree_view_find_node returns TRUE, it ran out of tree
+   * before finding the tree and node belonging to path.  The
+   * path maps to a non-existing path and we will silently bail out.
+   * We unset tree and node to avoid further processing.
+   */
+  if (!row_is_separator (tree_view, NULL, path)
+      && _gtk_tree_view_find_node (tree_view, path, &tree, &node) == FALSE)
     {
       tree_view->priv->cursor =
-       gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
-                                         tree_view->priv->model,
-                                         path);
-      _gtk_tree_view_find_node (tree_view, path, &tree, &node);
+          gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
+                                            tree_view->priv->model,
+                                            path);
+    }
+  else
+    {
+      tree = NULL;
+      node = NULL;
     }
 
   if (tree != NULL)
index 14020084e9e6c4cd472a76c683a66e8daa5ab83d..3dcc44287f7e5210831bbf979249b269de90fa50 100644 (file)
@@ -96,6 +96,60 @@ test_bug_539377 (void)
                                                &path, NULL) == FALSE);
 }
 
+static void
+test_select_collapsed_row (void)
+{
+  GtkTreeIter child, parent;
+  GtkTreePath *path;
+  GtkTreeStore *tree_store;
+  GtkTreeSelection *selection;
+  GtkWidget *view;
+
+  /* Reported by Michael Natterer */
+  tree_store = gtk_tree_store_new (1, G_TYPE_STRING);
+  view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (tree_store));
+
+  gtk_tree_store_insert_with_values (tree_store, &parent, NULL, 0,
+                                     0, "Parent",
+                                     -1);
+
+  gtk_tree_store_insert_with_values (tree_store, &child, &parent, 0,
+                                     0, "Child",
+                                     -1);
+  gtk_tree_store_insert_with_values (tree_store, &child, &parent, 0,
+                                     0, "Child",
+                                     -1);
+
+
+  /* Try to select a child path. */
+  path = gtk_tree_path_new_from_indices (0, 1, -1);
+  gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path, NULL, FALSE);
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
+
+  /* Check that the parent is not selected. */
+  gtk_tree_path_up (path);
+  g_return_if_fail (gtk_tree_selection_path_is_selected (selection, path) == FALSE);
+
+  /* Nothing should be selected at this point. */
+  g_return_if_fail (gtk_tree_selection_count_selected_rows (selection) == 0);
+
+  /* Check that selection really still works. */
+  gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path, NULL, FALSE);
+  g_return_if_fail (gtk_tree_selection_path_is_selected (selection, path) == TRUE);
+  g_return_if_fail (gtk_tree_selection_count_selected_rows (selection) == 1);
+
+  /* Expand and select child node now. */
+  gtk_tree_path_append_index (path, 1);
+  gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
+
+  gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path, NULL, FALSE);
+  g_return_if_fail (gtk_tree_selection_path_is_selected (selection, path) == TRUE);
+  g_return_if_fail (gtk_tree_selection_count_selected_rows (selection) == 1);
+
+  gtk_tree_path_free (path);
+}
+
 int
 main (int    argc,
       char **argv)
@@ -104,6 +158,8 @@ main (int    argc,
 
   g_test_add_func ("/TreeView/cursor/bug-546005", test_bug_546005);
   g_test_add_func ("/TreeView/cursor/bug-539377", test_bug_539377);
+  g_test_add_func ("/TreeView/cursor/select-collapsed_row",
+                   test_select_collapsed_row);
 
   return g_test_run ();
 }